---@class RiichiMahjong.GameLogic : Base.GameLogic
local GameLogic = Fk.Base.GameLogic:subclass("RiichiMahjong.GameLogic")

local MJ = require "packages.mahjong.utility.mj_utility"
local TurnData = require "packages.mahjong.riichi_mahjong.core.turn_data"
-- 导入初始化好的Engine实例而不是Engine类
local Engine = require "packages.mahjong.riichi_mahjong"
local Meld = require "packages.mahjong.riichi_mahjong.core.meld"

---@class RiichiMahjong.GameLogic
---@field public room RiichiMahjong.Room
---@field public records RiichiMahjong.TurnData[] @ 游戏记录

function GameLogic:run()
  self:adjustSeats()
  self:init();

  self:action();
end

function GameLogic:init()
  local room = self.room
  
  room.prevailing_wind = MJ.Wind.East;
  room:setPlayerProperty(room.players[1], "role", "East")
  room:setPlayerProperty(room.players[2], "role", "South")
  room:setPlayerProperty(room.players[3], "role", "West")
  room:setPlayerProperty(room.players[4], "role", "North")
end

function GameLogic:action()
  local room = self.room
  -- 初始化点数
  for _, player in ipairs(room.players) do
    room:setPlayerProperty(player, "point", 25000)
  end
  -- 清空记录
  self.records = {}

  local all_cards = {}
  room.card_pile = {}
  room.dead_wall = {}
  for i,_ in pairs(Engine.all_tiles) do
    table.insert(all_cards, i)
  end
  table.shuffle(all_cards)
  --|王牌12|东13|南13|西13|北13|牌山59-136
  room.dead_wall = table.slice(all_cards, 1, 13)
  room.players[1].player_tiles = table.slice(all_cards, 13, 26)
  room.players[2].player_tiles = table.slice(all_cards, 26, 39)
  room.players[3].player_tiles = table.slice(all_cards, 39, 52)
  room.players[4].player_tiles = table.slice(all_cards, 52, 65)
  room.card_pile = table.slice(all_cards, 65, #all_cards)
  room.shown_dora_num = 1
  room.first_round = true
  room:setup()
  -- 设置初始当前玩家为东位玩家（第一个玩家）
  room.current = room.players[1]

  -- 游戏
  while true do
    self:hand()
  end
end

function GameLogic:hand()
  local room = self.room
  --TODO: 检测是否流局
  self:draw(room.current)
  room.turn_data = TurnData:new(room.current.id)
  room.turn_num = 0
  
  while true do
    self:turn()
    if room.finished then
      break
    end
    room.current = room:getPlayerById(room.current.next.id)
  end
  room.prevailing_wind = (room.prevailing_wind + 1) % 4
end

function GameLogic:turn()
  local room = self.room
  local player = room.current

  room:newTurn()

  local req = Request:new(room.current, "RiichiMahjong.AskForTile")
  local dat = { ---@type RiichiMahjong.AskForTileSpec
    isDiscard = false,
    ryukyoku = false,
    kongs = {},
    disabledTiles = {},
    riichi = {},
  }
  
  local t

  --一般情况进回合先摸一张牌
  if room.turn_data.action == 1 then
    t = self:draw(player)
    dat.kongs = player:getKongs()
    dat.riichi = player:getRiichi()
    dat.ryukyoku = player:getRyukyoku()
  elseif room.turn_data.action == 2 then
    room:call(room.current, room.turn_data.meld)
    dat.isDiscard = true
  elseif room.turn_data.action == 3 or room.turn_data.action == 4 or room.turn_data.action == 5 then
    t = self:draw(player, 1)
    dat.kongs = player:getKongs()
    dat.riichi = player:getRiichi()
    dat.ryukyoku = player:getRyukyoku()
  elseif room.turn_data.action == 6 then
    room:win()
    return
  end
  req:setData(player, dat)
  req:setDefaultReply(player, {
    action = dat.isDiscard and 2 or 1,
    tile = dat.isDiscard and table.random(room.current.player_tiles) or t,
    meld = {}
  })
  req:ask()

  local result = req:getResult(player)
  local action = ((result == "" or result.action) and (dat.isDiscard and 2 or 1))
  room.turn_data.action = action
  room:turnEnd()
  -- TODO: 增加合法性判断防止作弊
  if action == 1 or action == 2 then
    local discard = Engine:getTileById(result.tile)
    local req = Request:new(room.players, "RiichiMahjong.AskForCall")
    for _, p in ipairs(room.players) do
      local cpkdat = p:getCPK(discard, p.next == room.current)
      req:setData(p, {---@type RiichiMahjong.AskForCallSpec
        chows = cpkdat[Meld.Type.Chow],
        pongs = cpkdat[Meld.Type.Pong],
        kongs = cpkdat[Meld.Type.Kong],
        rong = false,
        delay = math.random(1000)
      })
    end
    req:ask()
    local now_action = 0
    local real_responser = nil
    -- TODO: 增加合法性判断防止作弊
    for _, p in ipairs(room.players) do
      local result = req:getResult(p)
      if result ~= "" then
        --- action: 1-吃 2-碰 3-杠 4-荣和
        if result.action == 4 then
          table.insert(room.turn_data.winner, p.id)
        elseif result.action > now_action then
          real_responser = p
          now_action = result.action
          room.turn_data.meld = {
            type = result.action,
            tiles = result.tiles,
            from = room.current.id,
            which = discard.id
          }
        end
      end
    end
    if real_responser and #room.turn_data.winner == 0 then
      room:call(real_responser, room.turn_data.meld)
      room.current.id = real_responser.id
      if room.turn_data.meld.type ~= 3 then
        room.turn_data.action = 2
      else
        room.turn_data.action = 4
      end
    elseif #room.turn_data.winner > 0 then
      room:win()
    end
  elseif action == 3 then
  end

  
end

---摸一张麻将牌（摸牌前先检测牌山里是否有牌） 
---@param player RiichiMahjong.ServerPlayer
---@param from integer? @ 从哪摸 0-牌堆 1-补花
function GameLogic:draw(player, from)
  local room = self.room

  
  local card
  if from == 1 then
    card = self.room.card_pile[1]
    table.remove(self.room.card_pile, 1)
  else
    card = self.room.dead_wall[10 + room.shown_dora_num]
    table.remove(self.room.dead_wall, 10 + room.shown_dora_num)
    room.shown_dora_num = room.shown_dora_num + 1
  end

  table.insert(player.player_tiles, card)
  
  room:DrawTile(card, player)
  return card
end


return GameLogic
